// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <string>
#include <unordered_map>

#include <rapidjson/rapidjson.h>

namespace coin2::exchange::bitbank::api_util {

class OrderManager {
 public:
  using OrderMap = std::unordered_map<std::string, std::string>;
  using JsonValue = rapidjson::GenericValue<rapidjson::UTF8<>>;

 public:
  OrderManager() = default;
  OrderManager(const OrderManager&) = delete;
  OrderManager& operator=(const OrderManager&) = delete;

  auto GetOpenOrdersCopy() const -> OrderMap { return open_orders_; }
  auto GetOpenOrdersCopyBySymbol(const std::string& native_symbol) const -> OrderMap {
    OrderMap open_orders;
    for (auto& order : open_orders_) {
      if (order.second != native_symbol) {
        continue;
      }
      open_orders.emplace(order.first, order.second);
    }
    return open_orders;
  }

  void ProcessOpenOrder(const std::string& order_id, const std::string& pair) {
    AddOpenOrder(order_id, pair);
  }

  void ProcessOpenOrderByJson(const JsonValue& data) {
    if (!data.IsObject() || !data.HasMember("pair") || !data.HasMember("order_id")) {
      return;
    }
    auto&& pair = data["pair"].GetString();
    auto&& order_id = data["order_id"].GetString();
    AddOpenOrder(order_id, pair);
  }

  void ProcessClosedOrder(const std::string& order_id) {
    DelOpenOrder(order_id);
  }

  void ProcessClosedOrderByJson(const JsonValue& data) {
    if (!data.IsObject() || !data.HasMember("order_id")) {
      return;
    }
    auto&& order_id = data["order_id"].GetString();
    DelOpenOrder(order_id);
  }

  bool Find(const std::string& order_id) const { return open_orders_.count(order_id) > 0; }

 private:
  void AddOpenOrder(const std::string& order_id, const std::string& pair) {
    if (order_id.empty() || pair.empty()) {
      return;
    }
    if (open_orders_.count(order_id) > 0) {
      return;
    }
    open_orders_.emplace(order_id, pair);
  }

  void DelOpenOrder(const std::string& order_id) {
    if (order_id.empty()) {
      return;
    }
    if (open_orders_.count(order_id) == 0) {
      return;
    }
    open_orders_.erase(order_id);
  }

 private:
  OrderMap open_orders_;
};

}  // namespace coin2::exchange::bitbank::api_util
